package main

import (
	"database/sql"
	"github.com/redis/go-redis/v9"
	"log"
	"real-time-communication/utils"
	"strconv"
)

type Message struct {
	Id       int64  `json:"id" db:"id"`
	MsgId    string `json:"msgId" db:"msg_id"`
	MsgType  string `json:"msgType" db:"msg_type"`
	Sender   int    `json:"sender" db:"sender"`
	Receiver int    `json:"receiver" db:"receiver"`
	Content  string `json:"content" db:"content"`
	SendTime string `json:"sendTime" db:"send_time"`
}

type ResentMessage struct {
	Id         int64  `json:"id" db:"id"`
	UserId     int    `json:"userId" db:"user_id"`
	Nickname   string `json:"nickname" db:"nickname"`
	Avatar     string `json:"avatar" db:"avatar"`
	Content    string `json:"content" db:"content"`
	MsgId      string `json:"msgId" db:"msg_id"`
	IsLastRead bool   `json:"isLastRead"`
}

type MessageVo struct {
	Id       int64  `json:"id" db:"id"`
	MsgId    string `json:"msgId" db:"msg_id"`
	MsgType  string `json:"msgType" db:"msg_type"`
	Sender   int    `json:"sender" db:"sender"`
	Nickname string `json:"nickname" db:"nickname"`
	Avatar   string `json:"avatar" db:"avatar"`
	Content  string `json:"content" db:"content"`
	SendTime string `json:"sendTime" db:"send_time"`
}

func QueryResentMessage(userId int, searchContent string) []ResentMessage {
	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		log.Fatal("数据库打开失败:", err)
		return nil
	}
	defer db.Close()

	var res []ResentMessage

	if utils.IsEmpty(searchContent) {
		selectSQL := "SELECT m.id, u.user_id, u.nickname, u.avatar, m.content, m.msg_id FROM message AS m INNER JOIN user AS u ON u.user_id != ? AND (u.user_id = m.sender OR u.user_id = m.receiver) WHERE m.send_time IN (SELECT MAX(send_time) FROM message WHERE msg_id IN (SELECT DISTINCT msg_id FROM message WHERE sender = ? OR receiver = ?) GROUP BY msg_id) ORDER BY m.send_time DESC"
		stmt, err := db.Prepare(selectSQL)
		if err != nil {
			log.Fatal("数据库异常", err)
			return nil
		}
		defer stmt.Close()

		rows, err := stmt.Query(userId, userId, userId)
		if err != nil {
			log.Fatal("数据库异常", err)
			return nil
		}
		defer rows.Close()

		for rows.Next() {
			var msg ResentMessage
			err := rows.Scan(&msg.Id, &msg.UserId, &msg.Nickname, &msg.Avatar, &msg.Content, &msg.MsgId)
			if err != nil {
				log.Fatal("数据库异常", err)
				return nil
			}

			redisKey := "LastRead:" + strconv.Itoa(userId) + ":" + msg.MsgId
			result, err := Rdb.Get(Ctx, redisKey).Result()

			if err != redis.Nil {
				mId, err := strconv.ParseInt(result, 10, 64)
				if err == nil && mId < msg.Id {
					msg.IsLastRead = false
				} else {
					msg.IsLastRead = true
				}
			} else {
				msg.IsLastRead = false
			}

			res = append(res, msg)
		}
	} else {
		selectSQL := "SELECT m.id, u.user_id, u.nickname, u.avatar, m.content, m.msg_id FROM message AS m INNER JOIN user AS u ON u.user_id != ? AND (u.user_id = m.sender OR u.user_id = m.receiver) WHERE m.send_time IN (SELECT MAX(send_time) FROM message WHERE msg_id IN (SELECT DISTINCT msg_id FROM message WHERE sender = ? OR receiver = ?) AND u.nickname LIKE ? GROUP BY msg_id) ORDER BY m.send_time DESC"
		stmt, err := db.Prepare(selectSQL)
		if err != nil {
			log.Fatal("数据库异常", err)
			return nil
		}
		defer stmt.Close()

		rows, err := stmt.Query(userId, userId, userId, "%"+searchContent+"%")
		if err != nil {
			log.Fatal("数据库异常", err)
			return nil
		}
		defer rows.Close()

		for rows.Next() {
			var msg ResentMessage
			err := rows.Scan(&msg.Id, &msg.UserId, &msg.Nickname, &msg.Avatar, &msg.Content, &msg.MsgId)
			if err != nil {
				log.Fatal("数据库异常", err)
				return nil
			}

			redisKey := "LastRead:" + strconv.Itoa(userId) + ":" + msg.MsgId
			result, err := Rdb.Get(Ctx, redisKey).Result()

			if err != redis.Nil {
				mId, err := strconv.ParseInt(result, 10, 64)
				if err == nil && mId < msg.Id {
					msg.IsLastRead = false
				} else {
					msg.IsLastRead = true
				}
			} else {
				msg.IsLastRead = false
			}

			res = append(res, msg)
		}
	}
	return res
}

func QueryChatMessage(userId, targetId int) []MessageVo {
	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		log.Fatal("数据库打开失败:", err)
		return nil
	}
	defer db.Close()

	var res []MessageVo

	selectSQL := "SELECT m.id, m.msg_id, m.msg_type, m.sender, u.nickname, u.avatar, m.content, m.send_time FROM message AS m INNER JOIN user AS u ON m.sender = u.user_id WHERE (m.sender = ? AND m.receiver = ?) OR (m.sender = ? AND m.receiver = ?) ORDER BY m.send_time"
	stmt, err := db.Prepare(selectSQL)
	if err != nil {
		log.Fatal("数据库异常", err)
		return nil
	}
	defer stmt.Close()

	rows, err := stmt.Query(userId, targetId, targetId, userId)
	if err != nil {
		log.Fatal("数据库异常", err)
		return nil
	}
	defer rows.Close()

	for rows.Next() {
		var msg MessageVo
		err := rows.Scan(&msg.Id, &msg.MsgId, &msg.MsgType, &msg.Sender, &msg.Nickname, &msg.Avatar, &msg.Content, &msg.SendTime)
		if err != nil {
			log.Fatal("数据库异常", err)
			return nil
		}
		res = append(res, msg)
	}
	return res
}

func AddMessage(msg Message) bool {
	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		log.Fatal("数据库打开失败:", err)
		return false
	}
	defer db.Close()

	stmt, err := db.Prepare("INSERT INTO message (msg_id, msg_type, sender, receiver, content, send_time) VALUES (?, ?, ?, ?, ?, DATETIME('now'))")
	if err != nil {
		log.Println("数据库异常", err)
		return false
	}
	defer stmt.Close()

	_, err = stmt.Exec(msg.MsgId, msg.MsgType, msg.Sender, msg.Receiver, msg.Content)

	if err != nil {
		log.Fatal("数据库异常", err)
		return false
	}
	return true
}

func QueryLastTimeMessage(user1, user2 int) *MessageVo {
	db, err := sql.Open("sqlite3", "./RealTimeCommunication.db")
	if err != nil {
		log.Fatal("数据库打开失败:", err)
		return nil
	}
	defer db.Close()

	var res MessageVo
	
	stmt, err := db.Prepare("SELECT id, msg_id FROM message WHERE (sender = ? AND receiver = ?) OR (sender = ? AND receiver = ?) ORDER BY send_time DESC LIMIT 1")
	if err != nil {
		log.Fatal("数据库异常", err)
		return nil
	}
	defer stmt.Close()

	row := stmt.QueryRow(user1, user2, user1, user2)
	err = row.Scan(&res.Id, &res.MsgId)
	if err == sql.ErrNoRows || err != nil {
		return nil
	}
	return &res
}
